<?php
// core/Request.php - Optimized request handling
declare(strict_types=1);

namespace core;

class Request
{
    private array $get;
    private array $post;
    private array $server;
    private array $files;
    private array $cookies;
    private array $session;

    public function __construct()
    {
        $this->get     = filter_input_array(INPUT_GET, FILTER_SANITIZE_SPECIAL_CHARS) ?? [];
        $this->post    = filter_input_array(INPUT_POST, FILTER_SANITIZE_SPECIAL_CHARS) ?? [];
        $this->server  = filter_input_array(INPUT_SERVER, FILTER_SANITIZE_SPECIAL_CHARS) ?? [];
        $this->files   = $_FILES ?? [];
        $this->cookies = filter_input_array(INPUT_COOKIE, FILTER_SANITIZE_SPECIAL_CHARS) ?? [];
        $this->session = $_SESSION ?? [];
    }

    public function get(string $key, mixed $default = null): mixed
    {
        return $this->get[$key] ?? $default;
    }

    public function post(string $key, mixed $default = null): mixed
    {
        return $this->post[$key] ?? $default;
    }

    public function file(string $key): ?array
    {
        return $this->files[$key] ?? null;
    }

    public function getMethod(): string
    {
        return $this->server['REQUEST_METHOD'] ?? 'GET';
    }

    public function getUri(): string
    {
        return $this->server['REQUEST_URI'] ?? '/';
    }

    public function session(string $key, mixed $default = null): mixed
    {
        return $this->session[$key] ?? $default;
    }

    public function generateCsrfToken(): string
    {
        if (empty($this->session['csrf_token'])) {
            $this->session['csrf_token'] = bin2hex(random_bytes(32));
            $_SESSION['csrf_token'] = $this->session['csrf_token']; // Persist to session
        }
        return $this->session['csrf_token'];
    }

    public function validateCsrfToken(?string $token): bool
    {
        return $token !== null && hash_equals($this->session['csrf_token'] ?? '', $token);
    }

    // Validate input with custom rules
    public function validate(array $rules): array
    {
        $errors = [];
        foreach ($rules as $field => $rule) {
            $value = $this->post($field, $this->get($field));
            if ($rule['required'] && empty($value)) {
                $errors[$field] = "Field {$field} is required";
            } elseif ($rule['type'] === 'email' && !filter_var($value, FILTER_VALIDATE_EMAIL)) {
                $errors[$field] = "Field {$field} must be a valid email";
            } elseif ($rule['type'] === 'int' && !filter_var($value, FILTER_VALIDATE_INT)) {
                $errors[$field] = "Field {$field} must be an integer";
            }
        }
        return $errors;
    }
}